/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ui;

import object.TetrisTask;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import object.Control;
import object.Piece;
import object.PieceCreator;
import object.Square;
import util.ImageUtil;

/**
 *
 * @author XiaoLong
 */
public class GamePanel extends javax.swing.JPanel {

    private Image bkg;
    public final static int WIDTHSIZE = 10;
    public final static int HIGHTSIZE = 20;
    //游戏格子
    private int[][] squares;
    //控制器
    public Control control;
    //方块创造器
    private PieceCreator creator;
    // 当前方块
    private Piece piece;
    //当前Piece的开始X座标
    private int BEGIN_X = Piece.SQUARE_BORDER * 4;
    //当前Piece的开始Y座标
    private int BEGIN_Y = -Piece.SQUARE_BORDER;
    //下一个大方块对象
    private Piece nextPiece;
    //下一个Piece的X座标
    private NextPanel nextPanel;
    //主面板
    private MainFrame mainFrame;
    //计时器
    private Timer timer;
    //游戏线程
    private TetrisTask tetrisTask;
    //级别
    private int level = 1;
    //分数
    private int score = 0;
    //行数
    private int lines = 0;
    private ImageUtil imageUtil;

    public GamePanel() {
        initComponents();
    }

    public GamePanel(MainFrame mainFrame) {
        initComponents();
        initSquares();
        this.imageUtil = ImageUtil.getInstance();
        //bkg = imageUtil.getImage("images/gameBkg.png");
        bkg = imageUtil.getImage("/images/Bkg-black.png");
        creator = new PieceCreator();
        this.piece = creator.createPiece(BEGIN_X, BEGIN_Y);
        this.control = new Control(this, this.piece, this.squares);
        this.mainFrame = mainFrame;
        this.tetrisTask = new TetrisTask(this);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.drawImage(bkg, this.getX(), this.getY(), null);
        if (piece != null) {
            imageUtil.paintPiece(g, piece);
        }
        if (squares == null) {
            return;
        }
        for (int i = 0; i < squares.length; i++) {
            for (int j = 0; j < squares[i].length; j++) {
                int s = squares[i][j];
                if (s > 0) {
                    g.drawImage(imageUtil.colors[s - 1], Piece.SQUARE_BORDER * i, Piece.SQUARE_BORDER * j, null);
                }
            }
        }

    }

    /**
     * 初始化界面二维数组
     */
    private void initSquares() {
        this.squares = new int[GamePanel.WIDTHSIZE][GamePanel.HIGHTSIZE];
    }

    //一个Piece对象完成下降
    private void finishDown() {
        //将当前的Piece设置为下一个Piece
        this.piece = this.nextPiece;
        //设置新的Piece座标
        this.piece.setSquaresXLocation(BEGIN_X);
        this.piece.setSquaresYLocation(BEGIN_Y);
        this.control.setPiece(piece);
        //下一个Piece
        this.repaint();
        showNextPanel();
    }

    //进行下一个
    public void showNext() {
        //判断是否失败
        if (isLost()) {
            this.timer.cancel();
            this.piece = null;
            JOptionPane.showMessageDialog(this, "Game Over!");
            this.mainFrame.beginBtn.setEnabled(true);
            initSquares();
            this.piece = creator.createPiece(BEGIN_X, BEGIN_Y);
            this.control = new Control(this, this.piece, this.squares);
            this.score = 0;
            this.level = 1;
            this.lines = 0;
            return;
        }
        //将当前的Piece中的所有Square加入加界面二维数组中
        appendToSquares();
        //消除行
        cleanRows();
        finishDown();
    }

    //显示下一个面板
    public void showNextPanel() {
        this.nextPiece = this.creator.createPiece(0, 0);
        this.nextPanel.setNextPiece(nextPiece);
    }

    //得到可以清理行集合
    private void cleanRows() {
        //使用一个集合保存被删除的行的索引
        List<Integer> rowIndexs = new ArrayList<>();
        int k = 0;//消除的行数
        int s;
        for (int j = GamePanel.HIGHTSIZE - 1; j >= 0; j--) {
            for (int i = 0; i < GamePanel.WIDTHSIZE; i++) {
                s = this.squares[i][j];
                if (s == 0) {//如果遇到空则直接进行下一行判断
                    break;
                }
                if (i == GamePanel.WIDTHSIZE - 1) {//如果是最后一列 说明该行需要消除
                    for (int ii = 0; ii < 10; ii++) {
                        this.squares[ii][j] = 0;
                    }
                    rowIndexs.add(j);//记录这一行
                    k++;
                }
            }
        }
        if (k > 0) {
            this.lines += k;
            this.mainFrame.linesLabel.setText(String.valueOf(this.lines));
            try {
                Thread.sleep(200);
            } catch (InterruptedException ex) {
                System.out.println(ex.toString());
            }
            //System.out.println("总共消除" + k + "行");
            addScore(k);//根据消除的行数加分
            handleDown(rowIndexs);
        }
    }

    //处理行消除后其他Square的"下降", 参数为被删除的行的索引集合
    private void handleDown(List<Integer> rowIndexs) {
        int size = 0;
        int i = 0;
        for (int j = rowIndexs.get(0); j > 0; j--) {
            if (i < rowIndexs.size() && j == rowIndexs.get(i)) {
                size++;
                i++;
            }
            if (rowDown(j - 1, size) == 0 && i == rowIndexs.size()) {
                break;
            }
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException ex) {
            System.out.println(ex.toString());
        }
        this.repaint();
    }

    //j为行数  size为移动的行数
    private int rowDown(int j, int size) {
        int s;
        int k = 0;//移动的个数
        for (int i = 0; i < this.squares.length; i++) {
            s = this.squares[i][j];
            if (s != 0) {
                this.squares[i][j + size] = s;
                this.squares[i][j] = 0;
                k++;
            }
        }
        return k;
    }

    //加入分数
    private void addScore(int rows) {
        //加分
        switch (rows) {
            case 1: {
                this.score += 100;
                break;
            }
            case 2: {
                this.score += 300;
                break;
            }
            case 3: {
                this.score += 500;
                break;
            }
            case 4: {
                this.score += 800;
                break;
            }
        }
        this.mainFrame.scoreLabel.setText(String.valueOf(score));
        if ((this.score / 3000) >= this.level) {
            this.level += 1;
            this.mainFrame.levelLabel.setText(String.valueOf(this.level));
            //重新设置定时器
            this.timer.cancel();
            this.timer = new Timer();
            this.tetrisTask = new TetrisTask(this);
            int time = 1000 / this.level;
            timer.schedule(this.tetrisTask, 0, time);
        }
    }

    private void appendToSquares() {
        if (piece == null) {
            return;
        }
        List<Square> squaresList = this.piece.getSquares();
        //遍历Piece中的Square
        for (Square square : squaresList) {
            int i = (square.getBeginX() / Piece.SQUARE_BORDER);
            int j = (square.getBeginY() / Piece.SQUARE_BORDER);
            //得到当前界面中的Square
            this.squares[i][j] = square.getImage();
        }
        piece = null;
        this.repaint();
    }

    //判断是否失败, true为失败, false反之
    private boolean isLost() {
        if (this.control.isBlock() && this.control.getPiece().getMinYLocation() <= 0) {
            this.control = null;
            this.squares = null;

            return true;
        }
        return false;
    }

    public Piece getPiece() {
        return piece;
    }

    public void setPiece(Piece piece) {
        this.piece = piece;
    }

    public Piece getNextPiece() {
        return nextPiece;
    }

    public void setNextPiece(Piece nextPiece) {
        this.nextPiece = nextPiece;
    }

    public JPanel getNextPanel() {
        return nextPanel;
    }

    public void setNextPanel(NextPanel nextPanel) {
        this.nextPanel = nextPanel;
    }

    public Timer getTimer() {
        return timer;
    }

    public void setTimer(Timer timer) {
        if (timer != null) {
            this.timer = timer;
            int time = 1000 / this.level;
            this.timer.schedule(this.tetrisTask, 0, time);
        }
    }

    public TetrisTask getTetrisTask() {
        return tetrisTask;
    }

    public void setTetrisTask(TetrisTask tetrisTask) {
        this.tetrisTask = tetrisTask;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setBackground(new java.awt.Color(0, 0, 0));
        setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 255), 1, true));
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        setMaximumSize(new java.awt.Dimension(180, 360));
        setMinimumSize(new java.awt.Dimension(180, 360));
        setName(""); // NOI18N
        setPreferredSize(new java.awt.Dimension(180, 360));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 180, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 360, Short.MAX_VALUE)
        );

        getAccessibleContext().setAccessibleName("");
        getAccessibleContext().setAccessibleDescription("");
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
